package com.iwomy.secureplat.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.iwomy.secureplat.admin.api.entity.SysDept;
import com.iwomy.secureplat.common.core.util.R;
import com.iwomy.secureplat.common.data.datascope.DataScope;
import com.iwomy.secureplat.platform.dto.AlarmLoggingDTO;
import com.iwomy.secureplat.platform.entity.*;
import com.iwomy.secureplat.platform.mapper.AlarmLoggingMapper;
import com.iwomy.secureplat.platform.service.AlarmLoggingService;
import com.iwomy.secureplat.platform.utils.DataScopeUtils;
import com.iwomy.secureplat.platform.utils.DeptFillUtils;
import com.iwomy.secureplat.platform.utils.RemoteDeptUtils;
import com.iwomy.secureplat.platform.vo.AlarmLoggingVO;
import com.iwomy.secureplat.platform.vo.ThreeDaysAlarmCountVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 报警记录表
 *
 * @author pig
 * @date 2023-11-21 15:08:54
 */
@Service
public class AlarmLoggingServiceImpl extends ServiceImpl<AlarmLoggingMapper, AlarmLoggingEntity> implements AlarmLoggingService {

	@Autowired
	private RemoteDeptUtils remoteDeptUtils;

	@Override
	public Page<AlarmLoggingVO> deviceDetailsPage(Page page, AlarmLoggingDTO alarmLoggingDTO) {
		//查询
		MPJLambdaWrapper<AlarmLoggingEntity> wrapper = createBaseWrapper();

		if (ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeviceTypeId())) {
			wrapper.eq(AlarmLoggingEntity::getDeviceTypeId, alarmLoggingDTO.getDeviceTypeId());
		}
		if (ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeviceModelId())) {
			wrapper.eq(AlarmLoggingEntity::getDeviceModelId, alarmLoggingDTO.getDeviceModelId());
		}
		if (ObjectUtil.isNotEmpty(alarmLoggingDTO.getImei())) {
			wrapper.eq(AlarmLoggingEntity::getImei, alarmLoggingDTO.getImei())
					.orderByDesc(AlarmLoggingEntity::getCreateTime);
		}
		if (ArrayUtil.isNotEmpty(alarmLoggingDTO.getCreateTime())) {
			wrapper.ge(AlarmLoggingEntity::getCreateTime, alarmLoggingDTO.getCreateTime()[0]).le(AlarmLoggingEntity::getCreateTime,
					alarmLoggingDTO.getCreateTime()[1]);
		}
		// 子查询部分
		String subQuery = "(SELECT MAX(create_time) FROM alarm_logging  WHERE imei = t.imei)";
		wrapper.apply("t.create_time = " + subQuery);

		return this.getBaseMapper().selectJoinPage(page, AlarmLoggingVO.class, wrapper);
	}

	@Override
	public Page<AlarmLoggingVO> getImeiList(Page page, AlarmLoggingDTO alarmLoggingDTO) {
		MPJLambdaWrapper<AlarmLoggingEntity> wrapper = createBaseWrapper();
		return this.getBaseMapper().selectJoinPage(page, AlarmLoggingVO.class, wrapper);
	}

	@Override
	public AlarmLoggingVO getById(Long id) {
		//多表查询
//		MPJLambdaWrapper<AlarmLoggingEntity> wrapper = createBaseWrapper().eq(AlarmLoggingEntity::getId, id);
//		AlarmLoggingVO alarmLogging = this.getBaseMapper().selectJoinOne(AlarmLoggingVO.class, wrapper);
		AlarmLoggingEntity alarmLoggingEntity = this.getBaseMapper().selectById(id);
		return BeanUtil.copyProperties(alarmLoggingEntity, AlarmLoggingVO.class);
	}

	@Override
	public Page<AlarmLoggingVO> getAlarmLoggingPage(Page page, AlarmLoggingDTO alarmLoggingDTO) {
		//查询
		MPJLambdaWrapper<AlarmLoggingEntity> wrapper = new MPJLambdaWrapper<>();
		wrapper.selectAll(AlarmLoggingEntity.class);
		wrapper.selectAs(BasicInstallLocationEntity::getDetailAddress, AlarmLoggingVO::getDetailAddress);
//		wrapper.selectAs(AlarmEventTypeEntity::getEventTypeName, AlarmLoggingVO::getEventTypeName);
		wrapper.leftJoin(BasicInstallLocationEntity.class, BasicInstallLocationEntity::getId, AlarmLoggingEntity::getInstallLocationId);
//		wrapper.leftJoin(AlarmEventTypeEntity.class, AlarmEventTypeEntity::getId, AlarmLoggingEntity::getEventTypeId);
		wrapper.eq(StrUtil.isNotEmpty(alarmLoggingDTO.getEventTypeName()),AlarmLoggingEntity::getEventTypeName,alarmLoggingDTO.getEventTypeName());
		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeviceTypeId()),
				AlarmLoggingEntity::getDeviceTypeId, alarmLoggingDTO.getDeviceTypeId());
		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeviceModelId()), AlarmLoggingEntity::getDeviceModelId,
				alarmLoggingDTO.getDeviceModelId());

		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getState()), AlarmLoggingEntity::getState,
				alarmLoggingDTO.getState());
		List<Long> list = DataScopeUtils.getList();
		wrapper.in(ObjectUtil.isNotEmpty(list), AlarmLoggingEntity::getDeptId,
				list);
		wrapper.like(ObjectUtil.isNotEmpty(alarmLoggingDTO.getImei()), AlarmLoggingEntity::getImei,
				alarmLoggingDTO.getImei()).orderByDesc(AlarmLoggingEntity::getCreateTime);
		if (ArrayUtil.isNotEmpty(alarmLoggingDTO.getCreateTime())) {
			wrapper.ge(AlarmLoggingEntity::getCreateTime,
					alarmLoggingDTO.getCreateTime()[0]).le(AlarmLoggingEntity::getCreateTime,
					alarmLoggingDTO.getCreateTime()[1]);
		}
		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getEventTypeId()),
				AlarmLoggingEntity::getEventTypeId, alarmLoggingDTO.getEventTypeId());

		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getInstallLocationId()),
				AlarmLoggingEntity::getInstallLocationId, alarmLoggingDTO.getInstallLocationId());

		if (ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeptLimit())) {
			if (alarmLoggingDTO.getDeptLimit() == 20) {
				wrapper.in(AlarmLoggingEntity::getDeptId, alarmLoggingDTO.getDeptId());
			} else {
				List<SysDept> deptList = (List<SysDept>) remoteDeptUtils.getDescendantList(alarmLoggingDTO.getDeptId()).getData();
				List<Long> deptIds = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
				if (deptIds != null) wrapper.in(AlarmLoggingEntity::getDeptId, deptIds);
			}
		} else {
			if (ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeptId())) {
				wrapper.in(AlarmLoggingEntity::getDeptId, alarmLoggingDTO.getDeptId());
			}
		}

		page = this.getBaseMapper().selectJoinPage(page, AlarmLoggingVO.class, wrapper);
		DeptFillUtils.fill(page);
		return page;
	}

	@Override
	public long countByScope(LambdaQueryWrapper<AlarmLoggingEntity> wrapper, DataScope dataScope) {
		return this.getBaseMapper().selectCount(wrapper);
	}

	@Override
	public long selectCountByImei(String imei) {
		return count(Wrappers.lambdaQuery(AlarmLoggingEntity.class).eq(AlarmLoggingEntity::getImei, imei)
				.eq(AlarmLoggingEntity::getState, 20));
	}

	@Override
	public AlarmLoggingEntity oneByImeiDesc(String imei) {
		return getOne(Wrappers.lambdaQuery(AlarmLoggingEntity.class).eq(AlarmLoggingEntity::getImei, imei)
				.eq(AlarmLoggingEntity::getState, 20)
				.orderByDesc(AlarmLoggingEntity::getCreateTime).last("limit 1"));
	}

	@Override
	public List<AlarmLoggingEntity> listByScope(LambdaQueryWrapper<AlarmLoggingEntity> wrapper, DataScope dataScope) {
		List<AlarmLoggingEntity> list = this.getBaseMapper().selectListByScope(wrapper, dataScope);
		return list;
	}

	@Override
	public R threeDaysAlarmCount() {
		LambdaQueryWrapper<AlarmLoggingEntity> wrapper = Wrappers.lambdaQuery();
		List<AlarmLoggingEntity> list = this.baseMapper.selectListByScope(wrapper, new DataScope());
		List<Long> alarmLoggingId = list.stream().map(AlarmLoggingEntity::getId).collect(Collectors.toList());

		ThreeDaysAlarmCountVO threeDaysAlarmCountVO = new ThreeDaysAlarmCountVO();
		if (ObjectUtil.isNotEmpty(alarmLoggingId)) {
			LocalDateTime now = LocalDateTime.now();
			LocalDateTime threeDaysBefore = now.minusHours(72);
			LambdaQueryWrapper<AlarmLoggingEntity> queryWrapper = Wrappers.lambdaQuery();
			queryWrapper.between(AlarmLoggingEntity::getCreateTime, threeDaysBefore, now); // 报警时间在近 3 天内
			queryWrapper.in(AlarmLoggingEntity::getId, alarmLoggingId);
			List<AlarmLoggingEntity> alarmRecordList = this.getBaseMapper().selectList(queryWrapper);
			// 已处理的记录数
			long handledCount = alarmRecordList.stream()
					.filter(record -> record.getState() == 10)
					.count();
			// 未处理的记录数
			long unhandledCount = alarmRecordList.stream()
					.filter(record -> record.getState() == 20)
					.count();
			threeDaysAlarmCountVO.setThreeDaysAlarmCount((long) alarmRecordList.size());
			threeDaysAlarmCountVO.setThreeDaysHandledCount(handledCount);
			threeDaysAlarmCountVO.setThreeDaysUnhandledCount(unhandledCount);

		}
		return R.ok(threeDaysAlarmCountVO);
	}

	@Override
	public List export(AlarmLoggingDTO alarmLoggingDTO) {
		//查询
		MPJLambdaWrapper<AlarmLoggingEntity> wrapper = new MPJLambdaWrapper<>();
		wrapper.selectAll(AlarmLoggingEntity.class);
		wrapper.selectAs(BasicInstallLocationEntity::getDetailAddress, AlarmLoggingVO::getDetailAddress);
//		wrapper.selectAs(AlarmEventTypeEntity::getEventTypeName, AlarmLoggingVO::getEventTypeName);
		wrapper.leftJoin(BasicInstallLocationEntity.class, BasicInstallLocationEntity::getId, AlarmLoggingEntity::getInstallLocationId);
//		wrapper.leftJoin(AlarmEventTypeEntity.class, AlarmEventTypeEntity::getId, AlarmLoggingEntity::getEventTypeId);
		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeviceTypeId()),
				AlarmLoggingEntity::getDeviceTypeId, alarmLoggingDTO.getDeviceTypeId());
		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeviceModelId()), AlarmLoggingEntity::getDeviceModelId,
				alarmLoggingDTO.getDeviceModelId());

		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getState()), AlarmLoggingEntity::getState,
				alarmLoggingDTO.getState());
		List<Long> list = DataScopeUtils.getList();
		wrapper.in(ObjectUtil.isNotEmpty(list), AlarmLoggingEntity::getDeptId,
				list);
		wrapper.like(ObjectUtil.isNotEmpty(alarmLoggingDTO.getImei()), AlarmLoggingEntity::getImei,
				alarmLoggingDTO.getImei()).orderByDesc(AlarmLoggingEntity::getCreateTime);
		if (ArrayUtil.isNotEmpty(alarmLoggingDTO.getCreateTime())) {
			wrapper.ge(AlarmLoggingEntity::getCreateTime,
					alarmLoggingDTO.getCreateTime()[0]).le(AlarmLoggingEntity::getCreateTime,
					alarmLoggingDTO.getCreateTime()[1]);
		}
		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getEventTypeId()),
				AlarmLoggingEntity::getEventTypeId, alarmLoggingDTO.getEventTypeId());

		wrapper.eq(ObjectUtil.isNotEmpty(alarmLoggingDTO.getInstallLocationId()),
				AlarmLoggingEntity::getInstallLocationId, alarmLoggingDTO.getInstallLocationId());

		if (ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeptLimit())) {
			if (alarmLoggingDTO.getDeptLimit() == 20) {
				wrapper.in(AlarmLoggingEntity::getDeptId, alarmLoggingDTO.getDeptId());
			} else {
				List<SysDept> deptList = (List<SysDept>) remoteDeptUtils.getDescendantList(alarmLoggingDTO.getDeptId()).getData();
				List<Long> deptIds = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
				if (deptIds != null) wrapper.in(AlarmLoggingEntity::getDeptId, deptIds);
			}
		} else {
			if (ObjectUtil.isNotEmpty(alarmLoggingDTO.getDeptId())) {
				wrapper.in(AlarmLoggingEntity::getDeptId, alarmLoggingDTO.getDeptId());
			}
		}

		List<AlarmLoggingVO> alarmLoggingVOS = this.getBaseMapper().selectJoinList(AlarmLoggingVO.class, wrapper);
		DeptFillUtils.fill(alarmLoggingVOS);

		return alarmLoggingVOS;
	}

	private MPJLambdaWrapper<AlarmLoggingEntity> createBaseWrapper() {
		//多表查询
		MPJLambdaWrapper<AlarmLoggingEntity> wrapper = new MPJLambdaWrapper<>();
		wrapper.selectAll(AlarmLoggingEntity.class)
				.selectAs(BasicInstallLocationEntity::getAddress, AlarmLoggingVO::getInstallAddress)
				.selectAs(BasicDeviceTypeEntity::getTypeName, AlarmLoggingVO::getEventTypeName)
				.selectAs(BasicDeviceModelEntity::getDeviceModelName, AlarmLoggingVO::getDeviceModelName)

				.leftJoin(BasicInstallLocationEntity.class, BasicInstallLocationEntity::getId, AlarmLoggingEntity::getInstallLocationId)
				.leftJoin(BasicDeviceTypeEntity.class, BasicDeviceTypeEntity::getId, AlarmLoggingEntity::getDeviceTypeId)
				.leftJoin(BasicDeviceModelEntity.class, BasicDeviceModelEntity::getId, AlarmLoggingEntity::getDeviceModelId);

		return wrapper;
	}

}